﻿using System;
using FVXCOMDIDOLib;

namespace Common
{
    public class FAST_IO : I_IO_Card
    {
        FvxDido m_dido ;
        private readonly static object locker = new object();
        public static readonly FAST_IO instance = new FAST_IO();
        System.Timers.Timer tmr = new System.Timers.Timer(10);
        static readonly object lockWrite=new object();
        volatile ushort _ReadData = 0;
        volatile ushort Trg = 0;
        volatile ushort Continue = 0;
        public event Action<ushort> TrigEvent;
        public bool isOpen { get; set; }
        public ushort ReadData { get { return _ReadData; } set { _ReadData = value; } }
        private bool inited=false;
        public uint m_Write = 0;
        public ushort tag { get; set; }
        private FAST_IO()
        {
            try
            {
                m_dido = new FvxDidoClass();
                tmr.Elapsed += tmr_Elapsed;
                Start();
            }
            catch (Exception)
            {
                
              //  throw;
            }
        }

        public void Start()
        {
            try
            {
                if (!inited)
                {
                    m_dido.DeviceType = DIDO_DEVICE_TYPE.deviceFIO01;
                    m_dido.Open();                
                    inited = true;
                }
                if (!tmr.Enabled)
                {                
                    tmr.Start();
                }
                isOpen = true;
         //       WriteBit(GenneralConfig.instance.module.DO_RUN, true);              
            }
            catch(Exception ex)
            {
                isOpen = false;
          //      throw;         
            }
        }

        public void Stop()
        {
            tmr.Stop();
            isOpen = false;
          
        }

        ~FAST_IO()
        {
            if (m_dido != null && isOpen)
            {
                m_dido.Write(0x00);
                m_dido.Close();
                m_dido = null;
            }
        }

        public void AddSubscriber(Action<ushort> method)
        {
            TrigEvent += method;
        }

        void tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            lock (locker)
            {
                tmr.Stop();
                _ReadData = (ushort)(Read() & 0xffff);
                Trg = (ushort)(_ReadData & (_ReadData ^ Continue));
                Continue = _ReadData;
                if (Trg != 0 && TrigEvent != null)
                {
                    tag |= Trg;
                    TrigEvent(Trg);                  
                }
                tmr.Start(); 
            }
        }
        public void WriteBit(int nBit, bool value)
        {
            lock (lockWrite)
            {
                if (isOpen)
                {
                    if (value)
                    {
                        m_Write |= (ushort)(1 << nBit);
                    }
                    else
                    {
                        m_Write &= (ushort)(~(1 << nBit));
                    }
                }
                Write(m_Write);
            }
        }
        public uint Read()
        {
            int value = 0;
            if (isOpen)
                m_dido.Read(out value);
            return (uint)value;
        }
        public void Write(uint Value)
        {
            if (isOpen)
                m_dido.Write((int)Value);
        }
        public bool ReadBit(uint nBit)
        {
            bool value = false;
            if (isOpen)
            {
                int pattern = 1 << ((int)nBit);
                value = (Read() & pattern) > 0 ? true : false;
            }
            return value;
        }

    }
}
